package main.java.com.async.app;

import com.alibaba.fastjson.JSONObject;
import main.java.com.async.middleware.JavaFxControllerMiddleware;
import main.java.com.async.tools.AsyncWoodTool;
import main.java.com.async.tools.CustomizeUtil;
import main.java.com.async.tools.LogMessage;
import com.ptc.cipjava.jxthrowable;
import com.ptc.pfc.pfcAsyncConnection.*;
import com.ptc.pfc.pfcExceptions.XToolkitNotFound;
import com.ptc.pfc.pfcSession.Session;
import javafx.scene.control.ScrollPane;
import javafx.scene.text.TextFlow;

import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * @author Administrator
 *
 */

/**
 * @author Administrator
 *
 */
public class AsyncWoodTookitMain extends AsyncActionListener_u {

	// ---------------------------------------------------
	// JavaFx 控件对象申明
	// ---------------------------------------------------
	private static ScrollPane _scrollpane_info;
	private static TextFlow _textflow_info;
	// ---------------------------------------------------

	private static AsyncConnection _connection;
	private static Session _session;
	private static boolean exit_flag = false;
	private static String _creo_path; // creo启动路径
	private static String _msg_file; // UICommand程序中的信息文件
	private static String _menu_file; // UICommand中的菜单文件
	private static String _connectionid_files; // connection id 的文件
	private static Boolean _is_start_new_creo = false; // 用于判断能否加载Creo本体菜单程序
	private static AsyncWoodTool _asyncWoodTool; // 自定义异步工具的实例化对象

	private static final String ROOT_PATH = System.getProperty("user.dir");
	private static final String APP_ID = "AsyncWoodTookit"; // UICommand的标识符

	/**
	 * MainApp constructor MainApp 构造函数
	 *
	 */
	public AsyncWoodTookitMain() {

	}

	public void initializeCreo() throws IOException, jxthrowable {
		loadpfcasyncmt();
		loadConfigSetting();
		connectToCreo();
		if(_connection != null){
			addTerminationListener();
			_session = _connection.GetSession();
		}
		else {
			JavaFxControllerMiddleware.cacheCreoInfo("请检查Creo是否已经启动", "red");
		}
	}

	/**
	 * 外部获取Session
	 * @return session
	 */
	public Session getSession() {
		return _session;
	}

	/**
	 * 外部获取connection
	 * @return connection
	 */
	public AsyncConnection getConnection() {
		return _connection;
	}

	/**
	 * 加载pfcasyncmt.dll
	 */
	private static void loadpfcasyncmt() {
		try {
			System.loadLibrary("pfcasyncmt");
		} catch (UnsatisfiedLinkError error) {
			JavaFxControllerMiddleware.cacheCreoInfo("无法加载 J-Link library pfcasyncmt.dll "
					+ "请核实JNI pfcasyncmt.dll路径设置是否正确", "red");
			return;
		}
	}

	/**
	 * 等待Creo内部命令的事件响应
	 *
	 * @throws jxthrowable
	 */
	private static void waitForEventRespond() throws jxthrowable {
		while (!exit_flag) {
			try {
				_connection.WaitForEvents();
				Thread.sleep(1000);
			}
			catch (InterruptedException ex) {
			}
		}

		try {
			Thread.sleep(1000);
			_connection.EventProcess();
		}
		catch (InterruptedException ex) {
		}

	}

	/**
	 * 添加Creo终止监听器，监听本类
	 *
	 * @throws jxthrowable
	 * @throws FileNotFoundException
	 */
	private void addTerminationListener() throws jxthrowable, FileNotFoundException {
		try {
			_connection.AddActionListener(this);
		} catch (Exception e) {
			// TODO: handle exception
			LogMessage.logError(e);
		}
		JavaFxControllerMiddleware.cacheCreoInfo( "终止监听器已添加。", null);
	}

	/**
	 * Termination handler - from the AsyncActionListener interface.
	 *
	 * @throws jxthrowable
	 */
	public void OnTerminate(TerminationStatus status) throws jxthrowable {
		_connection.Disconnect(null);
		_connection.End();
		JavaFxControllerMiddleware.cacheCreoInfo("与Creo已断开连接!", null);
		exit_flag = true;
	}

	/**
	 * 尝试通过connectionId连接Creo,如果不行则启动Creo
	 *
	 * @throws IOException
	 * @throws jxthrowable
	 */
	private void connectToCreo() throws IOException, jxthrowable {
		ConnectionId connectionId = null;
//		初始化CustomizeUtil类
		CustomizeUtil customizeUtil = new CustomizeUtil();
//		判断connectionIdFiles是否存在，若存在则获取连接id
		if (customizeUtil.checkFileExist(_connectionid_files)) {
			String exRepConnectionId = CustomizeUtil.readFileToString(_connectionid_files);
			connectionId = pfcAsyncConnection.ConnectionId_Create(exRepConnectionId);
		} else {
//			如果文件不存在就生成一个空文件
			customizeUtil.msgRecordToFile("", _connectionid_files);
		}
//		尝试通过connection id连接Creo
		connectToCreoById(connectionId);

		if (_connection == null) {
//			连接当前电脑的任意正在运行的Creo且又无法从通过connectionid连接Creo
			connectToSpecificUserCreo("", "", null, null, customizeUtil);
////			暂时无法解决子线程阻塞问题,故注释掉
////			依然无法连接Creo,则启动一个Creo
			if (_connection == null) {
				return;
//				startNewCreo(customizeUtil);
			}
		}
	}

	/**
	 * 启动一个Creo
	 *
	 * @param customizeUtil 自定义工具类
	 * @throws jxthrowable
	 * @throws IOException
	 */
	private void startNewCreo(CustomizeUtil customizeUtil) throws jxthrowable, IOException {
		JavaFxControllerMiddleware.cacheCreoInfo("启动一个Creo！", null);
		try {
			_connection = pfcAsyncConnection.AsyncConnection_Start(_creo_path, null);
			System.out.println("startNewCreo thread name:" + Thread.currentThread().getName());
		} catch (Exception e) {
			// TODO: handle exception
			LogMessage.logError(e, "Creo启动失败,请检查config.json中Parametric.exe的路径是否正确！");
			return;
		}
		customizeUtil.msgRecordToFile(_connection.GetConnectionId().GetExternalRep(), _connectionid_files);
//		用于判断能否加载Creo本体菜单程序
		_is_start_new_creo = true;
		JavaFxControllerMiddleware.cacheCreoInfo( "程序已连接上Creo！", null);
	}

	/**
	 * 通过connectionId来连接Creo
	 *
	 * @param connectionId 当前正在运行的Creo的connection id
	 * @return 如果连接成功返回true，否则就返回false
	 * @throws jxthrowable
	 */
	private void connectToCreoById(ConnectionId connectionId) throws jxthrowable {
		try {
			_connection = pfcAsyncConnection.AsyncConnection_ConnectById(connectionId, null, null);
			JavaFxControllerMiddleware.cacheCreoInfo("程序已通过connection id连接上Creo！", null);
//			用于判断能否加载Creo本体菜单程序
			_is_start_new_creo = false;
		} catch (XToolkitNotFound x) {
			// TODO: handle exception
//			无法通过connectionid连接Creo可以新开一个Creo，可以捕捉异常也可以不捕捉
//			LogMessage.logWarn(x);
			JavaFxControllerMiddleware.cacheCreoInfo(
					"文本中的connection Id 无效," + "程序无法通过当前的connection Id 连接Creo！", "red");
		}
	}

	/**
	 * 连接当前已启动的某一个用户的Creo
	 *
	 * @param Display       正在使用Creo的显示器名称，如果为null则匹配任意显示器。如果为空字符串，则假定为localhost
	 * @param UserID        连接正在使用Creo的用户，若为null，则匹配任意用户。若假定为空字符串，则假定为当前用户
	 * @param TextPath      保存消息和菜单文件的路径，若无外部信息或者菜单，则需填null
	 * @param TimeoutSec    以秒为单位的时间，用于等待Creo响应连接请求的时间。填写null则采用默认连接超时。
	 * @param customizeUtil 自定义工具类
	 * @throws jxthrowable
	 * @throws IOException
	 */
	private void connectToSpecificUserCreo( /* optional */ String Display, /* optional */ String UserID,
			/* optional */ String TextPath, /* optional */ Integer TimeoutSec, CustomizeUtil customizeUtil)
			throws jxthrowable, IOException {
		try {
			_connection = pfcAsyncConnection.AsyncConnection_Connect(Display, UserID, TextPath, TimeoutSec);
			customizeUtil.msgRecordToFile(_connection.GetConnectionId().GetExternalRep(), _connectionid_files);
			JavaFxControllerMiddleware.cacheCreoInfo("程序已连接上当前电脑上正在运行中的一个Creo！", null);
			_is_start_new_creo = false;
		} catch (XToolkitNotFound x) {
			// TODO: handle exception
//			LogMessage.logWarn(x);
			JavaFxControllerMiddleware.cacheCreoInfo("Creo 未启动,当前无法通过UserID直接连接Creo!", "red");
		}

	}

	/**
	 * 加载config中的配置内容，初始化变量
	 *
	 * @throws IOException
	 */
	private void loadConfigSetting() throws IOException {
		String configFilePath = ROOT_PATH + "//setting//config.json";
		String config = CustomizeUtil.readFileToString(configFilePath);
//		config加载为空或失败就退出程序
		if (config == null) {
			JavaFxControllerMiddleware.cacheCreoInfo("config为空,请检查config内容及路径!", "red");
			return;
		}
//		解析字符串为json对象
		JSONObject jsonObject = JSONObject.parseObject(config);
//		加载config中设置的路径
		_creo_path = jsonObject.getString("CreoPath");
		_msg_file = jsonObject.getString("MsgFile");
		_menu_file = jsonObject.getString("MenuFfile");
		_connectionid_files = jsonObject.getString("ConnectionID");
	}

}
